46. URL Encode/Decode
46.1: Encode Query String with [System.Web.HttpUtility]::UrlEncode()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | $scheme = 'https'
$url_format = '{0}://example.vertigion.com/foos?{1}'
$qs_data = @{
'foo1' = 'bar1'
'foo2' = 'complex;/?:@&=+$, bar''"'
'complex;/?:@&=+$, foo''"' = 'bar2'
}
[System.Collections.ArrayList] $qs_array = @()
foreach ($qs in $qs_data.GetEnumerator())
{
$qs_key = [System.Web.HttpUtility]::UrlEncode($qs.Name)
$qs_value = [System.Web.HttpUtility]::UrlEncode($qs.Value)
$null = $qs_array.Add("${qs_key}=${qs_value}")
}
$url = $url_format -f @([uri]::"UriScheme${scheme}", ($qs_array -join '&'))
|
With [System.Web.HttpUtility]::UrlEncode(), you will notice that spaces are turned into plus signs (+) instead of %20:
| https://example.vertigion.com/foos?
foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&
complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1
|
46.2: Quick Start: Encoding
| $url1 = [uri]::EscapeDataString("http://test.com?test=my value")
# url1: http%3A%2F%2Ftest.com%3Ftest%3Dmy%20value
|
| $url2 = [uri]::EscapeUriString("http://test.com?test=my value")
# url2: http://test.com?test=my%20value
|
| # HttpUtility requires at least .NET 1.1 to be installed.
$url3 = [System.Web.HttpUtility]::UrlEncode("http://test.com?test=my value")
# url3: http%3a%2f%2ftest.com%3ftest%3dmy+value
|
Note: More info on HTTPUtility.
46.3: Quick Start: Decoding
Note: these examples use the variables created in the Quick Start: Encoding above.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | # url1: http%3A%2F%2Ftest.com%3Ftest%3Dmy%20value
[uri]::UnescapeDataString($url1)
# Returns: http://test.com?test=my value
# url2: http://test.com?test=my%20value
[uri]::UnescapeDataString($url2)
# Returns: http://test.com?test=my value
# url3: http%3a%2f%2ftest.com%3ftest%3dmy+value
[uri]::UnescapeDataString($url3)
# Returns: http://test.com?test=my+value
# Note: There is no `[uri]::UnescapeUriString()`;
# which makes sense since the `[uri]::UnescapeDataString()`
# function handles everything it would handle plus more.
# HttpUtility requires at least .NET 1.1 to be installed.
# url1: http%3A%2F%2Ftest.com%3Ftest%3Dmy%20value
[System.Web.HttpUtility]::UrlDecode($url1)
# Returns: http://test.com?test=my value
# HttpUtility requires at least .NET 1.1 to be installed.
# url2: http://test.com?test=my%20value
[System.Web.HttpUtility]::UrlDecode($url2)
# Returns: http://test.com?test=my value
# HttpUtility requires at least .NET 1.1 to be installed.
# url3: http%3a%2f%2ftest.com%3ftest%3dmy+value
[System.Web.HttpUtility]::UrlDecode($url3)
# Returns: http://test.com?test=my value
|
Note: More info on HTTPUtility.
46.4: Encode Query String with [uri]::EscapeDataString()
| $scheme = 'https'
$url_format = '{0}://example.vertigion.com/foos?{1}'
$qs_data = @{
'foo1'='bar1';
'foo2'= 'complex;/?:@&=+$, bar''"';
'complex;/?:@&=+$, foo''"'='bar2';
}
|
| [System.Collections.ArrayList] $qs_array = @()
foreach ($qs in $qs_data.GetEnumerator()) {
$qs_key = [uri]::EscapeDataString($qs.Name)
$qs_value = [uri]::EscapeDataString($qs.Value)
$qs_array.Add("${qs_key}=${qs_value}") | Out-Null
}
$url = $url_format -f @([uri]::"UriScheme${scheme}", ($qs_array - join '&'))
|
With [uri]::EscapeDataString(), you will notice that the apostrophe (') was not encoded:
| https://example.vertigion.com/foos?
foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22&
complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1
|
46.5: Decode URL with [uri]::UnescapeDataString()
Encoded with [uri]::EscapeDataString()
First, we'll decode the URL and Query String encoded with [uri]::EscapeDataString() in the above example:
| https://example.vertigion.com/foos?
foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22&
complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | $url =
'https://example.vertigion.com/foos?foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar''%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo''%22=bar2&foo1=bar1'
$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) {
$url_parts = @{
'Scheme' = $Matches[ 2 ];
'Server' = $Matches[ 4 ];
'Path' = $Matches[ 5 ];
'QueryString' = $Matches[ 7 ];
'QueryStringParts' = @{}
}
foreach ($qs in $query_string.Split('&')) {
$qs_key, $qs_value = $qs.Split('=')
$url_parts.QueryStringParts.Add(
[uri]::UnescapeDataString($qs_key),
[uri]::UnescapeDataString($qs_value)
) | Out-Null
}
} else {
Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"
}
|
This gives you back [hashtable]$url_parts; which equals ( Note: the spaces in the complex parts are spaces ):
| Name Value
---- -----
Scheme https
Path /foos
Server example.vertigion.com
QueryString
foo2=complex%3B%2F%3F%3A% 40 % 26 %3D%2B% 24 %2C%20bar'%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%
22 =bar2&foo1=bar1
QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
|
| $url_parts.QueryStringParts
|
| Name Value
---- -----
foo2 complex;/?:@&=+$, bar'"
complex;/?:@&=+$, foo'" bar2
foo1 bar1
|
Encoded with [System.Web.HttpUtility]::UrlEncode()
Now, we'll decode the URL and Query String encoded with [System.Web.HttpUtility]::UrlEncode() in the above
example:
| https://example.vertigion.com/foos?
|
| foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&
complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | $url =
'https://example.vertigion.com/foos?foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1'
$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) {
$url_parts = @{
'Scheme' = $Matches[2];
'Server' = $Matches[4];
'Path' = $Matches[5];
'QueryString' = $Matches[7];
'QueryStringParts' = @{}
}
foreach ($qs in $query_string.Split('&')) {
$qs_key, $qs_value = $qs.Split('=')
$url_parts.QueryStringParts.Add(
[uri]::UnescapeDataString($qs_key),
[uri]::UnescapeDataString($qs_value)
) | Out-Null
}
} else {
Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"
}
|
This gives you back [hashtable]$url_parts, which equals ( Note: the spaces in the complex parts are plus signs (+) in the first part and spaces in the second part):
| Name Value
---- -----
Scheme https
Path /foos
Server example.vertigion.com
QueryString
foo2=complex%3b%2f%3f%3a% 40 % 26 %3d%2b% 24 %2c+bar% 27 % 22 &complex%3b%2f%3f%3a% 40 % 26 %3d%2b% 24 %2c+foo% 27 %
22 =bar2&foo1=bar1
QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
|
| $url_parts.QueryStringParts
|
| Name Value
---- -----
foo2 complex;/?:@&=+$, bar'"
complex;/?:@&=+$, foo'" bar2
foo1 bar1
|
46.6: Decode URL with [System.Web.HttpUtility]::UrlDecode()
Encoded with [uri]::EscapeDataString()
First, we'll decode the URL and Query String encoded with [uri]::EscapeDataString() in the above example:
| https://example.vertigion.com/foos?
foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22&
complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | $url =
'https://example.vertigion.com/foos?foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar''%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo''%22=bar2&foo1=bar1'
$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) {
$url_parts = @{
'Scheme' = $Matches[2];
'Server' = $Matches[4];
'Path' = $Matches[5];
'QueryString' = $Matches[7];
'QueryStringParts' = @{}
}
foreach ($qs in $query_string.Split('&')) {
$qs_key, $qs_value = $qs.Split('=')
$url_parts.QueryStringParts.Add(
[System.Web.HttpUtility]::UrlDecode($qs_key),
[System.Web.HttpUtility]::UrlDecode($qs_value)
) | Out-Null
}
} else {
Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"
}
|
This gives you back [hashtable]$url_parts; which equals ( Note: the spaces in the complex parts are spaces ):
| Name Value
---- -----
Scheme https
Path /foos
Server example.vertigion.com
QueryString
foo2=complex%3B%2F%3F%3A% 40 % 26 %3D%2B% 24 %2C%20bar'%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%
22 =bar2&foo1=bar1
QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
|
| $url_parts.QueryStringParts
|
| Name Value
---- -----
foo2 complex;/?:@&=+$, bar'"
complex;/?:@&=+$, foo'" bar2
foo1 bar1
|
Encoded with [System.Web.HttpUtility]::UrlEncode()
Now, we'll decode the URL and Query String encoded with [System.Web.HttpUtility]::UrlEncode() in the above
example:
| https://example.vertigion.com/foos?
|
| foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&
complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | $url =
'https://example.vertigion.com/foos?foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1'
$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) {
$url_parts = @{
'Scheme' = $Matches[2];
'Server' = $Matches[4];
'Path' = $Matches[5];
'QueryString' = $Matches[7];
'QueryStringParts' = @{}
}
foreach ($qs in $query_string.Split('&')) {
$qs_key, $qs_value = $qs.Split('=')
$url_parts.QueryStringParts.Add(
[System.Web.HttpUtility]::UrlDecode($qs_key),
[System.Web.HttpUtility]::UrlDecode($qs_value)
) | Out-Null
}
} else {
Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"
}
|
This gives you back [hashtable]$url_parts; which equals ( Note: the spaces in the complex parts are spaces ):
| Name Value
---- -----
Scheme https
Path /foos
Server example.vertigion.com
QueryString
foo2=complex%3b%2f%3f%3a% 40 % 26 %3d%2b% 24 %2c+bar% 27 % 22 &complex%3b%2f%3f%3a% 40 % 26 %3d%2b% 24 %2c+foo% 27 %
22 =bar2&foo1=bar1
QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
|
| $url_parts.QueryStringParts
|
| Name Value
---- -----
foo2 complex;/?:@&=+$, bar'"
complex;/?:@&=+$, foo'" bar2
foo1 bar1
|